using Digitalmes.Domain.Entities.Mes.Processes;
using Digitalmes.Domain.Entities.Mes.Qualities;
using Digitalmes.Domain.Entities.Mes.Reworks;

namespace Digitalmes.Application.Mes.Reworks.Doc.Commands;

/// <summary>
/// 更新在线返工工单命令。
/// </summary>
/// <param name="Doc"></param>
public sealed record UpdateOnlineReworkDocCommand(long Id, long[] DefectIds, long TargetOperationId, string? Remark) : IRequest<IResult<bool>>;

internal sealed class UpdateOnlineReworkDocCommandHandler(IRepository<ReworkDoc> repo,
    IRepository<ReworkDefect> defectRepo,
    IRepository<QcDefectDefine> defectDefineRepo,
    IRepository<ProcOperation> operationRepo)
    : IRequestHandler<UpdateOnlineReworkDocCommand, IResult<bool>>
{
    public async Task<IResult<bool>> Handle(UpdateOnlineReworkDocCommand request, CancellationToken cancellationToken)
    {
        var doc = await repo.GetByIdAsync(request.Id, cancellationToken);
        if (doc == null)
        {
            return Result.Failure("返工单不存在");
        }

        // 仅处于创建状态的返工单才可以取消
        if (doc.Status != ReworkStatusEnum.Created)
        {
            return Result.Failure("返工单已开始执行，不能编辑");
        }

        // 目标工序
        var operation = await operationRepo.GetByIdAsync(request.TargetOperationId, cancellationToken);
        if (operation == null)
        {
            return Result.Failure("未找到目标工序");
        }

        doc.TargetOperationId = request.TargetOperationId;
        doc.TargetOperationCode = operation.OpCode;
        doc.Remark = request.Remark;

        var ok = await repo.UpdateAsync(doc, m => new
        {
            m.TargetOperationId,
            m.TargetOperationCode,
            m.Remark,
        }, cancellationToken);

        // 更新缺陷
        var defects = await defectRepo.GetListAsync(m => m.ReworkId == doc.Id, cancellationToken);
        if (defects.Count > 0)
        {
            await defectRepo.DeleteAsync(defects, cancellationToken);
        }

        if (request.DefectIds.Length > 0)
        {
            var defectDefines = await defectDefineRepo.GetListAsync(m => request.DefectIds.Contains(m.Id), cancellationToken);
            if (defectDefines.Count > 0)
            {
                var defects2 = defectDefines.Select(m => new ReworkDefect
                {
                    ReworkId = doc.Id,
                    DefectId = m.Id,
                    DefectCode = m.DefectCode,
                    DefectName = m.DefectName,
                    DefectType = m.DefectType,
                    DefectTypeDesc = m.DefectTypeDesc,
                    DefectLevel = m.DefectLevel,
                }).ToList();

                await defectRepo.InsertRangeAsync(defects2, cancellationToken);
            }
        }

        return Result.From(ok);
    }
}
